#!/usr/bin/env python3
# @Date    : 2023-03-13
# @Author  : Bright (brt2@qq.com)
# @Link    : https://gitee.com/brt2
# @Version : v0.1.5

# 用于Termux/Jupyter环境下，模拟cv2操作

from .gvar import gLogger as logger

from PIL import Image
import numpy as np
try:
    from imageio.v2 import imread, imsave, imwrite
except ModuleNotFoundError:
    print("[!] 未能载入【imageio】模块")
    try:
        from cv2 import imread, imwrite
    except ModuleNotFoundError:
        print("[!] 未能载入【cv2】模块")


#####################################################################
# Classes
#####################################################################
import urllib.request
import os.path as osp

class WebCamera:
    """ 使用 IP-WebCamera  """
    def __init__(self, url):
        self.set_url(url)

    def set_ip(self, ip_addr, port):  # deprecated
        # url = f'http://{ip_addr}:{port}'
        url = f'http://{ip_addr}:{port}/shot.jpg'
        self.set_url(url)

    def set_url(self, url):
        self.url = url

    def _cv2decode(self):
        import cv2

        imgResp = urllib.request.urlopen(self.url)
        data = imgResp.read()
        logger.debug(f">>> {type(data)} Length: {len(data)}")
        im = np.array(bytearray(data), dtype=np.uint8)
        return cv2.imdecode(im)

    def read(self):
        im = imread(self.url)
        # print(">>>", type(im), len(im), im.shape)
        return im

def _demo_webcam():
    cap = WebCamera("192.168.137.200:8080")
    im = cap.read()
    print(im.shape)
    cap.release()

class Cv2FakeCapture:
    def __init__(self, path=None):
        if path:
            self.set_img(path)
        else:
            self._img = None

    def set_img(self, path=None):
        if path is None:
            path = osp.join(osp.dirname(__file__), "demo.jpg")
        logger.debug(f">> Load Image: {path}")
        self._img = imread(path)

    def read(self):
        if self._img is None:
            # raise "请先设置图像: cap.set_test_img(path='...')"
            self.set_img(path=None)
        return self._img

def _demo_cv2fake():
    cap = Cv2FakeCapture("path/image.jpg")
    im = cap.read()
    print(im.shape)
    cap.release()

class VideoCapture:
    def __init__(self, arg, **kwargs):
        if isinstance(arg, int):  # 指定摄像头序号
            mode = "cv2"
            kwargs["id"] = arg
        # else:  "str"
        elif arg.find(":") >= 0:
            logger.info("[+] 使用网络摄像头")
            mode = "webcam"
            kwargs["ip_port"] = arg
        elif osp.exists(arg):
            logger.info(f"[+] Jupyter静态调试，使用本地图片模拟Video读取视频流")
            mode = "fake"
            kwargs["path"] = arg
        else:
            raise f"Unknown mode-arg: 【{arg}】"
        self.set_mode(mode, **kwargs)
        self.display = False  # 如开启窗口显示，则存储窗口title
        self.loop_running = True  # 是否暂停循环采集

    def set_mode(self, mode, **kwargs):
        """ return: 实际的摄像头实例对象"""
        global cv2

        assert mode in ["webcam", "cv2", "fake"]
        self._mode = mode

        if mode == "cv2":
            try:
                import cv2 as opencv
                cv2 = opencv
                self.instance = cv2.VideoCapture(kwargs["id"])
                return self.instance
            except ImportError:
                self._mode = "fake"

        if mode == "fake":
            self.instance = Cv2FakeCapture(kwargs["path"])
        elif mode == "webcam":
            self.instance = WebCamera(kwargs["ip_port"])
        return self.instance

    def read(self):
        """ 统一接口 """
        img = self.instance.read()
        if self._mode == "cv2":
            img = img[1]
            if self.display:
                cv2.imshow(self.display, img)
                if ord('q') == cv2.waitKey(10):
                    self.pause()
        return img

    def release(self):
        if self._mode == "cv2":
            self.instance.release()
        self.instance = None
        logger.info("[+] 摄像头已关闭")

    def pause(self):
        self.loop_running = not self.loop_running

    def is_running(self):
        return self.loop_running

    def display_window(self, win_title="cvs::VideoCapture"):
        if self._mode == "cv2":
            self.display = win_title
            cv2.namedWindow(win_title, cv2.WINDOW_NORMAL)  # cv2.WINDOW_AUTOSIZE
        else:
            logger.warning("[!] kwargs: 参数display仅支持【cv2】模式")

    def destroy_window(self):
        assert self.instance is None, "先执行release()操作再释放窗口"
        if self.display:
            cv2.destroyAllWindows()
        else:
            logger.warning("[!] 未开启display模式")

def run_as_webcam(url):
    cap = VideoCapture(url)
    try:
        while cap.is_running():
            im = cap.read()
            logger.debug(f">>> {im.shape}")
    finally:
        cap.release()

def run_as_camera(index):
    cap = VideoCapture(index)
    cap.display_window()
    while cap.is_running():
        im = cap.read()
        logger.debug(f">>> img: {im.shape}")
    cap.release()
    cap.destroy_window()

#####################################################################
# Jupyter Notebook Debug
#####################################################################

from PIL import ImageDraw, ImageFont

def putText(pimg, pos, text, *args, **kwargs):
    """ return the pimg（原对象，但内容已更新）

        常用kwargs:
        * fill: 填充颜色，例如 0: 黑色, 255: 红色, (255,255,255): 白色, (0,255,0): 绿色
        * font: string, like './data/Arial.ttf'
    """
    if kwargs.get("font"):
        kwargs["font"] = ImageFont.truetype(font=kwargs["font"])
    draw = ImageDraw.Draw(pimg)
    draw.text(pos, text, *args, **kwargs)
    return pimg

def boundBox(pimg, bbox, *args, **kwargs):
    """ return the pimg（原对象，但内容已更新）
        * bbox: 格式为 [xl, yl, xr, yr]

        常用kwargs:
        * outline='red'
        * width=1
    """
    draw = ImageDraw.Draw(pimg)
    draw.rectangle(bbox, *args, **kwargs)
    return pimg

#####################################################################

if __name__ == "__main__":
    # run_as_camera(0)
    run_as_webcam("http://192.168.137.77:1250/shot.jpg")
